package se.webbzon.boltzmann.object.geometry;

import java.awt.Color;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;

import javax.vecmath.Vector3d;

import se.webbzon.oschi01.worldobject.WorldObject;
import se.webbzon.oschi01.worldobject.WorldStaticObject;
import se.webbzon.oschi01.worldeditor.WorldStaticObjectDeflation;
import se.webbzon.oschi01.worldobject.appearance.SimpleAppearance3D;

public class UnmaskedGeometryDeflation extends WorldStaticObjectDeflation {
	
	private int appearanceGeometry;
	private boolean appearanceOpen;
	private int appearanceDivisions;
	private boolean appearanceBackfaced;
	
	private int renderingOrder;
	private String textureSetName;
	private double textureIndex, textureSpeed;
	private double xLayer, yLayer, zLayer;
	private Color blending;
	private float transparency;
	private double hRep, vRep;
	private double hOffset, vOffset;
	private double rotation;
	
	/*============================================================
	Constructors
	============================================================*/
	
	public UnmaskedGeometryDeflation(int deflationProperties) {
		this(deflationProperties,(WorldObject[]) null);
	}
	
	public UnmaskedGeometryDeflation(	int deflationProperties, 
										WorldObject[] dependencies) {
		super(deflationProperties,dependencies);
	}
	
	public UnmaskedGeometryDeflation(int deflationProperties, UnmaskedGeometry g) {
		this(deflationProperties,null,g); 
	}
	
	public UnmaskedGeometryDeflation(	int deflationProperties, 
										WorldObject[] dependencies, 
										UnmaskedGeometry g) {
		super(deflationProperties,dependencies,(WorldStaticObject) g);
		
		// Store the appearance
		final GeometryAppearance appearance = g.getGeometryAppearance();
		appearanceGeometry = appearance.getGeometry().ordinal();
		appearanceOpen = appearance.isOpen();
		appearanceDivisions = appearance.getDivisions();
		appearanceBackfaced = appearance.isBackfaced();
		
		// Store the attributes for the appearance
		final SimpleAppearance3D appearance3d = appearance.getAppearance();
		renderingOrder = appearance3d.getRenderingOrder();
		textureSetName = appearance.getTextureSetName();
		textureIndex = appearance3d.getTextureIndex();
		textureSpeed = appearance3d.getTextureSpeed();
		
		if (appearance3d.hasLayers()) {
			final Vector3d layerVector = new Vector3d();
			appearance3d.getLayer(layerVector);
			xLayer = layerVector.x;
			yLayer = layerVector.y;
			zLayer = layerVector.z;
		} 
		
		blending = appearance3d.getColor();
		
		if (appearance3d.hasTransparency())
			transparency = appearance3d.getTransparency();
		
		if (appearance3d.hasTextureRepeating()) {
			hRep = appearance3d.getHRep();
			vRep = appearance3d.getVRep();
		} else {
			hRep = 1;
			vRep = 1;
		}
		
		if (appearance3d.hasTextureTranslation()) {
			hOffset = appearance3d.getHOffset();
			vOffset = appearance3d.getVOffset();
		}
		
		if (appearance3d.hasTextureRotation())
			this.rotation = appearance3d.getRotation();
	}
	
	/*============================================================
	Public Methods
	============================================================*/
	
	/** Creates a new geometry appearance from the data stored in the
	 * unmasked geometry deflation. **/
	public GeometryAppearance makeGeometryAppearance() {
		return new GeometryAppearance(	GeometryEnum.values()[appearanceGeometry],
										appearanceOpen,
										appearanceDivisions,
										appearanceBackfaced,
										renderingOrder,
										textureSetName,
										textureIndex,textureSpeed,
										xLayer,yLayer,zLayer,
										blending,transparency,
										hRep,vRep,hOffset,vOffset,rotation);
	}

	@Override public void inflate(ByteBuffer buff) {
		super.inflate(buff);
		
		appearanceGeometry = buff.getInt();
		appearanceOpen = buff.get()!=0;
		appearanceDivisions = buff.getInt();
		appearanceBackfaced = buff.get()!=0;
		
		renderingOrder = buff.getInt(); 
		final short nameSize = buff.getShort();
		final byte[] nameData = new byte[nameSize];
		buff.get(nameData);
		try {
			textureSetName = new String(nameData,"UTF-8");
		} catch (UnsupportedEncodingException e) {
			textureSetName = null;
		}
		textureIndex = buff.getDouble();
		textureSpeed = buff.getDouble();
		xLayer = buff.getDouble();
		yLayer = buff.getDouble();
		zLayer = buff.getDouble();
		final int red, green, blue, alpha;
		red = 0x000000FF & buff.get();
		green = 0x000000FF & buff.get();
		blue = 0x000000FF & buff.get();
		alpha = 0x000000FF & buff.get();
		blending = new Color(red,green,blue,alpha);
		transparency = buff.getFloat();
		hRep = buff.getDouble();
		vRep = buff.getDouble();
		hOffset = buff.getDouble();
		vOffset = buff.getDouble();
		rotation = buff.getDouble(); 
	}

	@Override public ByteBuffer deflate(int allocate) {
		byte[] nameData;
		try {
			nameData = textureSetName.getBytes("UTF-8");
		} catch (UnsupportedEncodingException e) {
			nameData = new byte[0];
		}
		ByteBuffer buff = super.deflate(allocate + 104 + nameData.length);
		
		buff.putInt(appearanceGeometry);
		buff.put(appearanceOpen ? (byte) 1 : (byte) 0);
		buff.putInt(appearanceDivisions);
		buff.put(appearanceBackfaced ? (byte) 1 : (byte) 0);
		
		buff.putInt(renderingOrder);
		buff.putShort((short) textureSetName.length());
		buff.put(nameData);
		buff.putDouble(textureIndex);
		buff.putDouble(textureSpeed);
		buff.putDouble(xLayer);
		buff.putDouble(yLayer);
		buff.putDouble(zLayer);
		buff.put((byte) blending.getRed());
		buff.put((byte) blending.getGreen());
		buff.put((byte) blending.getBlue());
		buff.put((byte) blending.getAlpha());
		buff.putFloat(transparency);
		buff.putDouble(hRep);
		buff.putDouble(vRep);
		buff.putDouble(hOffset);
		buff.putDouble(vOffset);
		buff.putDouble(rotation);
		
		return buff;
	}

}
